/*
@title: Timing
@description: "Timing" is an action-packed game where a stickman battles bosses by shooting while skillfully dodging incoming attacks. Players must defeat all bosses without taking any hits to succeed. The game's focus lies in timing movements and attacks to outmaneuver the challenging bosses.
@author: Darsh Gupta
@tags: []
@addedOn: 2024-06-24
First time? Check out the tutorial game:
https://sprig.hackclub.com/gallery/getting_started

*/

const player = "p"
const boss = "b"
const proj = "k"

const winsfx = tune`
58.8235294117647: C4~58.8235294117647 + D4~58.8235294117647 + E5-58.8235294117647 + F5-58.8235294117647,
58.8235294117647: D4~58.8235294117647 + E4~58.8235294117647 + F4~58.8235294117647 + F5-58.8235294117647 + G5-58.8235294117647,
58.8235294117647: G4~58.8235294117647 + A4~58.8235294117647 + B4~58.8235294117647 + B5-58.8235294117647,
58.8235294117647: B4~58.8235294117647 + C5~58.8235294117647 + D5~58.8235294117647 + E5~58.8235294117647,
58.8235294117647: E5~58.8235294117647 + F5~58.8235294117647 + G5~58.8235294117647 + A5~58.8235294117647 + B5~58.8235294117647,
58.8235294117647: C4^58.8235294117647 + D4^58.8235294117647 + E4^58.8235294117647,
58.8235294117647: F4^58.8235294117647 + G4^58.8235294117647 + A4^58.8235294117647 + B4^58.8235294117647 + F5-58.8235294117647,
58.8235294117647: B4^58.8235294117647 + C5^58.8235294117647 + D5^58.8235294117647 + E5^58.8235294117647,
58.8235294117647: F5^58.8235294117647 + G5^58.8235294117647 + A5^58.8235294117647 + B5^58.8235294117647,
58.8235294117647: C4-58.8235294117647,
58.8235294117647: D4-58.8235294117647 + E4-58.8235294117647 + F4-58.8235294117647 + F5-58.8235294117647 + G5-58.8235294117647,
58.8235294117647: G4-58.8235294117647 + A4-58.8235294117647 + B4-58.8235294117647 + C5-58.8235294117647 + D5-58.8235294117647,
58.8235294117647: E5-58.8235294117647 + F5-58.8235294117647 + G5-58.8235294117647 + A5-58.8235294117647 + B5-58.8235294117647,
58.8235294117647: C4/58.8235294117647 + D4/58.8235294117647 + E4/58.8235294117647,
58.8235294117647: E4/58.8235294117647 + F4/58.8235294117647 + G4/58.8235294117647 + A4/58.8235294117647 + G5-58.8235294117647,
58.8235294117647: B4/58.8235294117647 + C5/58.8235294117647 + D5/58.8235294117647 + E5/58.8235294117647 + F5/58.8235294117647,
58.8235294117647: G5/58.8235294117647 + A5/58.8235294117647 + B5/58.8235294117647,
882.3529411764705`
const losesfx = tune`
153.0612244897959: B5~153.0612244897959 + A5~153.0612244897959,
153.0612244897959: A5~153.0612244897959 + G5~153.0612244897959,
153.0612244897959: G5~153.0612244897959 + F5~153.0612244897959 + E5~153.0612244897959,
153.0612244897959: E5~153.0612244897959 + D5~153.0612244897959 + C5~153.0612244897959 + B4~153.0612244897959,
153.0612244897959: B4~153.0612244897959 + A4~153.0612244897959 + G4~153.0612244897959,
153.0612244897959: G4~153.0612244897959 + F4~153.0612244897959 + E4~153.0612244897959 + B5^153.0612244897959 + A5^153.0612244897959,
153.0612244897959: E4~153.0612244897959 + D4~153.0612244897959 + A5^153.0612244897959 + G5^153.0612244897959 + F5^153.0612244897959,
153.0612244897959: D4~153.0612244897959 + C4~153.0612244897959 + F5^153.0612244897959 + E5^153.0612244897959 + D5^153.0612244897959,
153.0612244897959: C4~153.0612244897959 + D5^153.0612244897959 + C5^153.0612244897959,
153.0612244897959: C5^153.0612244897959 + B4^153.0612244897959 + A4^153.0612244897959,
153.0612244897959: A4^153.0612244897959 + G4^153.0612244897959,
153.0612244897959: G4^153.0612244897959 + F4^153.0612244897959 + E4^153.0612244897959,
153.0612244897959: E4^153.0612244897959 + D4^153.0612244897959 + B5-153.0612244897959,
153.0612244897959: D4^153.0612244897959 + C4^153.0612244897959 + B5-153.0612244897959 + A5-153.0612244897959 + G5-153.0612244897959,
153.0612244897959: C4^153.0612244897959 + G5-153.0612244897959 + F5-153.0612244897959 + E5-153.0612244897959,
153.0612244897959: E5-153.0612244897959 + D5-153.0612244897959 + C5-153.0612244897959 + B4-153.0612244897959,
153.0612244897959: B4-153.0612244897959 + A4-153.0612244897959 + G4-153.0612244897959,
153.0612244897959: G4-153.0612244897959 + F4-153.0612244897959,
153.0612244897959: E4-153.0612244897959 + D4-153.0612244897959 + B5/153.0612244897959 + A5/153.0612244897959,
153.0612244897959: D4-153.0612244897959 + C4-153.0612244897959 + A5/153.0612244897959 + G5/153.0612244897959 + F5/153.0612244897959,
153.0612244897959: C4-153.0612244897959 + E5/153.0612244897959 + D5/153.0612244897959 + C5/153.0612244897959,
153.0612244897959: C5/153.0612244897959 + B4/153.0612244897959 + A4/153.0612244897959 + G4/153.0612244897959,
153.0612244897959: G4/153.0612244897959 + F4/153.0612244897959 + E4/153.0612244897959,
153.0612244897959: E4/153.0612244897959 + D4/153.0612244897959 + C4/153.0612244897959,
153.0612244897959: C4/153.0612244897959,
1071.4285714285713`
const shootsfx = tune`
37.5: C4~37.5,
37.5: D4~37.5,
1125`
const fullwinsfx = tune`
77.51937984496124: C4/77.51937984496124,
77.51937984496124: C4/77.51937984496124 + D4/77.51937984496124,
77.51937984496124: D4/77.51937984496124,
77.51937984496124: D4/77.51937984496124 + E4/77.51937984496124,
77.51937984496124: E4/77.51937984496124,
77.51937984496124: E4/77.51937984496124 + F4/77.51937984496124,
77.51937984496124: F4/77.51937984496124,
77.51937984496124: F4/77.51937984496124,
77.51937984496124: G4/77.51937984496124,
77.51937984496124: G4/77.51937984496124,
77.51937984496124: A4/77.51937984496124,
77.51937984496124: A4/77.51937984496124,
77.51937984496124: A4/77.51937984496124 + B4/77.51937984496124,
77.51937984496124: B4/77.51937984496124,
77.51937984496124: B4/77.51937984496124 + C5/77.51937984496124,
77.51937984496124: C5/77.51937984496124,
77.51937984496124: C5/77.51937984496124 + D5/77.51937984496124,
77.51937984496124: D5/77.51937984496124,
77.51937984496124: D5/77.51937984496124 + E5/77.51937984496124,
77.51937984496124: E5/77.51937984496124,
77.51937984496124: E5/77.51937984496124,
77.51937984496124: E5/77.51937984496124 + F5/77.51937984496124,
77.51937984496124: F5/77.51937984496124 + G5/77.51937984496124,
77.51937984496124: G5/77.51937984496124,
77.51937984496124: G5/77.51937984496124 + A5/77.51937984496124,
77.51937984496124: A5/77.51937984496124,
77.51937984496124: A5/77.51937984496124 + B5/77.51937984496124,
77.51937984496124: B5/77.51937984496124,
77.51937984496124: B5/77.51937984496124,
77.51937984496124: B5-77.51937984496124,
77.51937984496124: B5-77.51937984496124,
77.51937984496124: B5-77.51937984496124`

setLegend(
  [ player, bitmap`
................
................
................
................
.......000......
.......030......
.......000......
........0.......
......00000.....
........0.......
........0.......
.......0.0......
................
................
................
................` ],
  [ boss, bitmap`
................
...4.......4....
....44...44.....
....44.4.44.....
......444.......
.....44944......
......444.......
....44.4.44.....
....44...44.....
...4.......4....
................
................
................
................
................
................`],
  [ proj, bitmap`
................
................
................
................
................
................
.......33.......
.......33.......
.......33.......
.......33.......
................
................
................
................
................
................` ],
)

setSolids([])

let level = 0
const levels = [
  map`
.............p.
...............
...............
...............
.......b.......
...............
...............
...............
...............
...............`,
  map`
...........
...........
...........
...b.......
...........
.....p.....
...........
........b..
...........
...........`,
  map`
.............
.b...........
.............
.............
......b......
.............
..b..........
.............
..........b..
.............
..p..........`,
  map`
p....................
.....................
.............b.......
....b................
.....................
.........b...........
.................b...
.....................
...b.................
...b.........b.......
...................b.
.......b...........b.
..b..................
............b....b...
......b..............
.....................`
]

setMap(levels[level])

setPushables({
  [ player ]: []
})

let projs = []
let lastproj = Date.now()
let bossprojs = []

class Projectile {
  constructor(id, x, y, dir, spd) {
    this.id = id
    this.x = x
    this.y = y
    this.dir = dir
    this.spd = spd
  }

  create() {
    addSprite(this.x, this.y, proj);
  }

  update() {
    clearTile(this.x, this.y)
    this.x += this.dir*this.spd
    if (this.x < width() && this.x >= 0) {
      this.create()
    }
    else {
      projs.splice(projs.findIndex(obj => obj.id === this.id))
    }
  }
}

onInput("s", () => {
  getFirst(player).y += 1
})
onInput("w", () => {
  getFirst(player).y -= 1
})
onInput("d", () => {
  getFirst(player).x += 1
})
onInput("a", () => {
  getFirst(player).x -= 1
})

onInput("j", () => {
  if (projs.length >= 5 || (Date.now() - lastproj < 700)) {return}
  projs.push(new Projectile(projs.length+1, getFirst(player).x-1, getFirst(player).y, -1, 1))
  lastproj = Date.now()
})
onInput("l", () => {
  if (projs.length >= 5 || (Date.now() - lastproj < 700)) {return}
  projs.push(new Projectile(projs.length+1, getFirst(player).x+1, getFirst(player).y, 1, 1))
  lastproj = Date.now()
})

const playerproj = setInterval(() => {
  for (let i = 0; i < projs.length; i++) {
    projs[i].update();
  }
}, 200)
const bossprojupdate = setInterval(() => {
  for (let i = 0; i < bossprojs.length; i++) {
    bossprojs[i].update();
  }
}, 200)

const bossproj = setInterval(() => {
  for (let i=0; i<getAll(boss).length; i++) {
    bossprojs.push(new Projectile(bossprojs.length+1, getAll(boss)[i].x+1, getAll(boss)[i].y, 1, 1))
    bossprojs.push(new Projectile(bossprojs.length+1, getAll(boss)[i].x-1, getAll(boss)[i].y, -1, 1))
    bossprojs.push(new Projectile(bossprojs.length+1, getAll(boss)[i].x, getAll(boss)[i].y+1, 1, 1))
    bossprojs.push(new Projectile(bossprojs.length+1, getAll(boss)[i].x, getAll(boss)[i].y-1, -1, 1))
    playTune(shootsfx)
  }
}, 1500)

function gameStop() {
  clearInterval(gameupdate)
  clearInterval(bossproj)
  clearInterval(playerproj)
  projs = []
  lastproj = Date.now()
  bossprojs = []
}

function fullWin() {
  gameStop()
  clearInterval(gameupdate)
  addText("You Win!", {x: 6, y: 6, color: color`7`})
  playTune(fullwinsfx)
}

const gameupdate = setInterval(() => {
  if ((getTile(getFirst(boss).x, getFirst(boss).y)).length > 1) {
    // win
    playTune(winsfx)
    bossprojs = []
    projs = []
    if (level+1 > 3) {
      fullWin()
      return
    } else {
      setMap(levels[level+1])
      level++
    }
    
  }
  if ((getTile(getFirst(player).x, getFirst(player).y)).length > 1) {
    addText("You Lose :(", {x: 4, y: 4, color: color`7`})
    playTune(losesfx)
    gameStop()
  }
}, 1)
